<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<!-- Copyright 2011 Native Client Authors.  All rights reserved.

     This page is used as the background page of the extension.  It runs in the
     extension's process, and cannot access the embedding page nor the code
     in the content script (test_bridge.js).  This page actually loads the
     NaCl module and runs some unit tests on it, outside of the Tester
     framework.  The results are published to the embedding page via an
     extension RPC request (see chrome.extension.onRequest.addListener() body).
     For more info on how extensions run, see:
         http://code.google.com/chrome/extensions/overview.html
-->
<head>
  <title> Chrome Extension Background Page </title>
  <META HTTP-EQUIV="Pragma" CONTENT="no-cache" />
  <META HTTP-EQUIV="Expires" CONTENT="-1" />
  <script type="text/javascript">
    var retries = 200;
    var retryWait = 50;

    /**
     * Determine if a NaCl module associated with an EMBED element has been
     * loaded.
     * @param {!Element} embed The EMBED element to check.
     * @return {bool} whether the module is loaded.
     */
    function isLoaded(embed) {
      return embed.readyState == 4;
    }

    /**
     * See if a NaCl module is loaded, and if not start a timer that polls
     * the EMBED element associated with the module.  Fail after |retries|
     * attempts.
     * @param {!Element} embed The EMBED element to test.
     * @param {!function} moduleDidLoad This callback is called when the
     *      NaCl module isloaded, or after the number of retires is exceeded.
     *      The callback is passed a bool argument indicating load success.
     */
    function waitForNaClModule(embed, moduleDidLoad, responseCallback) {
      if (isLoaded(embed)) {
        moduleDidLoad(true, responseCallback);
        return;
      }
      retries -= 1;
      if (retries <= 0) {
        moduleDidLoad(false, responseCallback);
        return;
      }
      // At this point, there is no discernible load error, and the module
      // has not yet loaded.  Continue to wait.
      responseCallback({type: 'log', message: 'Waiting...'});
      var callback = function() {
        waitForNaClModule(embed, moduleDidLoad, responseCallback);
      };
      setTimeout(callback, retryWait);
    }

    /**
     * Once the NaCl module is loaded, run some tests on it by attempting to
     * access a property and by calling a method.  Once these results are
     * obtained, send a message back to the embedding page with the results
     * via an RPC.  This function is provided as the callback to
     * waitForNaClModule().
     * @param {bool} loadSuccess Indicates whether the NaCl module was
     *     loaded.
     */
    function runAllTests(loadSuccess, responseCallback) {
      var response = { type: 'processTestResults',
                       testResults: {error: 0} };
      if (loadSuccess) {
        try {
          var messageListener = function(message) {
            // Get the test result.
            nacl_module.removeEventListener('message', messageListener, false);
            response.testResults.testResult = message.data;

            // Send the test result back to the main html page to check.
            // The main page will make sure the nexe loaded and that the
            // TestSimple test passed.
            responseCallback(response);
          };

          // Kick off the test.  The test will respond via post message.
          nacl_module.addEventListener("message", messageListener, false);
          nacl_module.postMessage("TestSimple");
        } catch (err) {
          // Trying to kick off the test failed, and threw a Javascript
          // exception.  Send the exception back to the main page so it can be
          // displayed.
          response.testResults.error = err.toString();
          responseCallback(response);
        }
      } else {
        // Notify the main page the nexe did not load.
        response.testResults.error = 'NaCl module failed to load';
        responseCallback(response);
      }
    }

    /**
     * This function is run from the embeding page, via the sendRequest()
     * mechanism in chrome.extension.
     * @return An object whose keys are the test ids, and values are the test
     *     results.
     */
    function loadModuleAndRunAllTests(responseCallback) {
      var nacl_module = document.getElementById('nacl_module');
      waitForNaClModule(nacl_module, runAllTests, responseCallback);
    }

    /**
     * Handle the 'runTests' RPC request.  This request is sent from the
     * test_bridge script.  For more info, see:
     *     http://code.google.com/chrome/extensions/messaging.html
     */
    // To deal with a race condition in Chrome extensions, the bridge script
    // will try to initiate multiple connections.  Only respond to the first
    // one we see.
    var connected = false;
    chrome.extension.onConnect.addListener(function(port) {
      if(!connected) {
        connected = true;
        loadModuleAndRunAllTests(function(response) {
          port.postMessage(response);
        });
      }
    });
  </script>
</head>
<body>
  <embed id="nacl_module"
         name="nacl_module"
         type="application/x-nacl"
         hidden="true"
         src="ppapi_test_example.nmf"
         />
  </body>
</html>

